-- ECE 251 Team B Transit Subsystem
-- This class defines a buffer for frames being moved out of the shared memory
-- April 9, 2007

Library ieee;
Use ieee.std_logic_1164.all;
Use work.transmit_package.all;

Entity FrameBuffer Is
	Port( Clock									: In Std_logic;
		  FSMinitialize							: In Std_logic;
		  FSMincomingBytes						: In Std_logic;
		  --FSMnibble0							: In Std_logic_vector(3 downto 0);
		  --FSMnibble1							: In Std_logic_vector(3 downto 0);
		  --FSMnibble2							: In Std_logic_vector(3 downto 0);
		  --FSMnibble3							: In Std_logic_vector(3 downto 0);
		  FSMfinished							: In Std_logic;
		  FSMOdd								: In Std_logic; 
		  MIIreadOut							: In Std_logic;
		  MIIframeReady							: Out Std_logic;
		  MIIdoneReadOut						: Out Std_logic;
		  --MIInextNibble						: Out Std_logic_vector(3 downto 0);
		  bufferFull							: Out Std_logic;
		  FIFOwrite								: Out Std_logic;
		  FIFOread								: Out Std_logic;
		  FIFOselect							: Out Std_logic_vector(3 downto 0)
	);
End FrameBuffer;

Architecture Behavior Of FrameBuffer Is

Signal firstOpen		: Integer;

Signal nextToReadLower	: Integer;

Type state_type Is (empty, reading, waiting, ready, streaming1, streaming2, streaming3, streaming4);

Signal state			: state_type;

Signal data				: Std_logic_vector(15 downto 0);

Begin
	Process
	Begin
		Wait Until Clock'Event And Clock = '1';
		
		If FSMinitialize = '1' Then
			state <= empty;
			firstOpen <= 0;
			nextToReadLower <= 0;
		End If;
		
		Case state Is
			When empty =>
				MIIframeReady <= '0';
				MIIdoneReadOut <= '0';
				firstOpen <= 0;
				
				nextToReadLower <= 0;
				
				If FSMincomingBytes = '1' Then
					state <= reading;
					FIFOwrite <= '1';
				Else
					state <= empty;
				End If;
				
			When reading =>	
				MIIframeReady <= '0';
				MIIdoneReadOut <= '0';			
												
				If FSMincomingBytes = '1' Then
					state <= reading;
					FIFOwrite <= '1';
					firstOpen <= firstOpen + 4;
				Else
					If FSMfinished = '1' Then
						state <= ready;
						FIFOwrite <= '0';
						If FSMOdd = '1' Then
							firstOpen <= firstOpen + 1;
						Else
							firstOpen <= firstOpen +3;
						End If;
					Else
						state <= waiting;
						FIFOwrite <= '0';
						firstOpen <= firstOpen + 4;
					End If;
				End If;
				
			When waiting =>
				MIIframeReady <= '0';
				MIIdoneReadOut <= '0';
				If FSMIncomingBytes = '1' Then
					state <= reading;
					FIFOwrite <= '1';
				Else
					state <= waiting;
					FIFOwrite <= '0';
				End If;
				
			When ready =>
				MIIframeReady <= '1';
				MIIdoneReadOut <= '0';
				If MIIreadOut = '1' Then
					state <= streaming1;
					FIFOread <= '0';
					FIFOselect <= "0010";
				Else
					state <= ready;
				End If;
				
			When streaming1 =>
				MIIframeReady <= '0';
				FIFOread <= '0';
				If nextToReadLower = firstOpen Then
					state <= empty;
					MIIdoneReadOut <= '0';
				Else
					state <= streaming2;
					FIFOselect <= "0100";
					
					If (nextToReadLower+1) = firstOpen Then
						MIIdoneReadOut <= '1';
					Else
						MIIdoneReadOut <= '0';
					End If;
					nextToReadLower <= nextToReadLower + 1;
				End If;
			When streaming2 =>
				MIIframeReady <= '0';
				FIFOread <= '0';
				If nextToReadLower = firstOpen Then
					state <= empty;
					MIIdoneReadOut <= '0';
				Else
					state <= streaming3;
					FIFOselect <= "1000";
					
					If (nextToReadLower+1) = firstOpen Then
						MIIdoneReadOut <= '1';
					Else
						MIIdoneReadOut <= '0';
					End If;
					nextToReadLower <= nextToReadLower + 1;
				End If;	
			When streaming3 =>
				MIIframeReady <= '0';
				If nextToReadLower = firstOpen Then
					state <= empty;
					MIIdoneReadOut <= '0';
				Else
					state <= streaming4;
					FIFOselect <= "0001";
					FIFOread <= '1';
					
					If (nextToReadLower+1) = firstOpen Then
						MIIdoneReadOut <= '1';
					Else
						MIIdoneReadOut <= '0';
					End If;
					nextToReadLower <= nextToReadLower + 1;
				End If;
			When streaming4 =>
				MIIframeReady <= '0';
				If nextToReadLower = firstOpen Then
					state <= empty;
					MIIdoneReadOut <= '0';
					FIFOread <= '0';
				Else
					state <= streaming1;
					FIFOread <= '0';
					FIFOselect <= "0010";
					
					If (nextToReadLower+1) = firstOpen Then
						MIIdoneReadOut <= '1';
					Else
						MIIdoneReadOut <= '0';
					End If;
					nextToReadLower <= nextToReadLower + 1;
				End If;
		End Case;
		
		If firstOpen = 3052 Then
			bufferFull <= '1';
		Else
			bufferFull <= '0';
		End If;
							
	End Process;

End Behavior;